//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <bulverde.h>
#include "display_def.h"
#define SPI_SCLK    36
#define SPI_TXD     13
#define SPI_FRM     14
#define SPI_RXD     11

#define LCD_nRESET  24
#define LCD_RS      77

void Gpio_SetDir(int gpio_num, int direction);
void Gpio_SetAFR(int gpio_num, int function);
void Gpio_SetOutLow(int gpio_num);
void Gpio_SetOutHigh(int gpio_num);

static void SPI2Init(void)
{
#define CKEN3_SSP2      (1 << 3)    /* SSP2 Unit Clock Enable */
    CKEN |= CKEN3_SSP2;

    Gpio_SetDir(SPI_SCLK, GPIO_PIN_OUT);
    Gpio_SetAFR(SPI_SCLK, GPIO_AS_AF2);
    //set spi_txd
    Gpio_SetDir(SPI_TXD, GPIO_PIN_OUT);
    Gpio_SetAFR(SPI_TXD, GPIO_AS_AF1);
    //set spi_frm  SPI_CS -- must be GPIO only because of the polarity of CS -- must be high for PMIC active
    Gpio_SetDir(SPI_FRM, GPIO_PIN_OUT);
    Gpio_SetAFR(SPI_FRM, GPIO_AS_GPIO);

    SSCR0_2 = (unsigned long)0x00C0020F;//Misubishi spi 16bits

    SSCR1_2 = (unsigned long)0x500007D8;

    SSCR0_2 |= 0x01 << 7;
}

void LcdHWSetup(void)
{
    int gpio_x;

    for (gpio_x = 58; gpio_x <= 76 ; gpio_x++) {
        Gpio_SetDir( gpio_x, GPIO_PIN_OUT );
        Gpio_SetOutLow(gpio_x);
        Gpio_SetAFR( gpio_x, GPIO_AS_AF2 );
    }

    Gpio_SetDir( 77, GPIO_PIN_OUT );
    Gpio_SetAFR( 77, GPIO_AS_GPIO );
    Gpio_SetOutHigh(77);

    Gpio_SetDir( 86, GPIO_PIN_OUT );
    Gpio_SetOutLow(86);
    Gpio_SetAFR( 86, GPIO_AS_AF2 );

    Gpio_SetDir( 87, GPIO_PIN_OUT );
    Gpio_SetOutLow(87);
    Gpio_SetAFR( 87, GPIO_AS_AF2 );
}

static void LcdReset(void)
{
    Gpio_SetDir(LCD_nRESET, GPIO_PIN_OUT);
    Gpio_SetAFR(LCD_nRESET, GPIO_AS_GPIO);

    Gpio_SetOutHigh(LCD_RS);

    Gpio_SetOutHigh(LCD_nRESET);

    ostdelay(10);

    Gpio_SetOutLow(LCD_nRESET);

    ostdelay(10);

    Gpio_SetOutHigh(LCD_nRESET);
}

void SPIWrite(unsigned short data)
{

    SSCR0_2 |= SSCR0_SSE;

    Gpio_SetOutLow(SPI_FRM);

    SSDR_2 = data;

    SSCR0_2 |= SSCR0_SSE;

    while( SSSR_2 & SSSR_BSY ) { }
    ;

    Gpio_SetOutHigh(SPI_FRM);
}

void LcdWriteIndx(unsigned short data)
{

    Gpio_SetOutLow(LCD_RS); //pull RS pin to low

    ostdelay(1);

    SPIWrite(data);

    Gpio_SetOutHigh(LCD_RS);   // pull RS pin to high
}

void LcdWriteData(unsigned short data)
{
    Gpio_SetOutHigh(LCD_RS);   // pull RS pin to high

    ostdelay(1);

    SPIWrite(data);

    Gpio_SetOutHigh(LCD_RS);   // pull RS pin to high
}

void LcdMitsubishiInit(void)
{
    // command reset
    ostdelay(1);

    LcdWriteIndx(0x0003);//R3
    LcdWriteData(0x0001);

    //oscillation circuit start
    LcdWriteIndx(0x003A);//R58
    LcdWriteData(0x0001);

    ostdelay(1);

    //gamma setting

    LcdWriteIndx(0x0052);//R82
    LcdWriteData(0x0021);

    LcdWriteIndx(0x0053);//R83
    LcdWriteData(0x0011);

    LcdWriteIndx(0x0024);//R36
    LcdWriteData(0x005C);

    LcdWriteIndx(0x0025);//R37
    LcdWriteData(0x005C);

    LcdWriteIndx(0x0026);//R38
    LcdWriteData(0x0022);

    LcdWriteIndx(0x0027);//R39
    LcdWriteData(0x0022);

    LcdWriteIndx(0x0061);//R97
    LcdWriteData(0x0021);

    LcdWriteIndx(0x0062);//R98
    LcdWriteData(0x001D);

    LcdWriteIndx(0x0063);//R99
    LcdWriteData(0x001E);

    LcdWriteIndx(0x0064);//R100
    LcdWriteData(0x001E);

    LcdWriteIndx(0x0065);//R101
    LcdWriteData(0x001E);

    LcdWriteIndx(0x0066);//R102
    LcdWriteData(0x0021);

    LcdWriteIndx(0x0067);//R103
    LcdWriteData(0x0010);

    LcdWriteIndx(0x0070);//R112
    LcdWriteData(0x0021);

    //DISPLAY SETTING
    LcdWriteIndx(0x0001);//R1
    LcdWriteData(0x0000);

    // RGB I/F SETTING-1
    LcdWriteIndx(0x0002);//R2
    LcdWriteData(0x00047);

    // COLOR MODE SETTING
    LcdWriteIndx(0x0004);//R4
    LcdWriteData(0x0000);

    // DISPLAY AREA SETTING
    LcdWriteIndx(0x0029);//R41
    LcdWriteData(0x0000);

    LcdWriteIndx(0x002A);//R42
    LcdWriteData(0x0000);

    LcdWriteIndx(0x002B);//R43
    LcdWriteData(0x00EF);

    LcdWriteIndx(0x002C);//R44
    LcdWriteData(0x013F);

    // GATE MODE SETTING
    LcdWriteIndx(0x0032);//R50
    LcdWriteData(0x0002);

    LcdWriteIndx(0x0033);//R51
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0037);//R55
    LcdWriteData(0x0000);

    // RGB I/F SETTING-2
    LcdWriteIndx(0x003C);//R60
    LcdWriteData(0x0000);

    LcdWriteIndx(0x003D);//R61
    LcdWriteData(0x013F);

    LcdWriteIndx(0x003E);//R62
    LcdWriteData(0x0041);//Horizontal and vertical back porch time

    // WINDOW AREA SETTING
    LcdWriteIndx(0x003F);//R63
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0040);//R64
    LcdWriteData(0x00EF);

    LcdWriteIndx(0x0041);//R65
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0042);//R66
    LcdWriteData(0x013F);

    // H TIMMING SETTING
    LcdWriteIndx(0x002E);//R46
    LcdWriteData(0x003C);

    LcdWriteIndx(0x004D);//R77
    LcdWriteData(0x0105);

    LcdWriteIndx(0x004E);//R78
    LcdWriteData(0x0001);

    LcdWriteIndx(0x004F);//R79
    LcdWriteData(0x0004);

    // DUMMY SOURCE OUTPUT
    LcdWriteIndx(0x0067);//R103
    LcdWriteData(0x0010);

    // WINDOW MODE SETTING
    LcdWriteIndx(0x0005);//R5
    LcdWriteData(0x0000);

    // Address SETTING
    LcdWriteIndx(0x0006);//R6
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0007);//R7
    LcdWriteData(0x0000);

    // POWER SETTING
    LcdWriteIndx(0x0018);//R24
    LcdWriteData(0x1F4B);

    LcdWriteIndx(0x0019);//R25
    LcdWriteData(0x0008);

    LcdWriteIndx(0x001A);//R26
    LcdWriteData(0x0055);

    LcdWriteIndx(0x001B);//R27
    LcdWriteData(0x0022);

    LcdWriteIndx(0x001C);//R28
    LcdWriteData(0x0CFD);

    LcdWriteIndx(0x001D);//R29
    LcdWriteData(0x0000);

    // VCOM SETTING
    LcdWriteIndx(0x001E);//R30
    LcdWriteData(0x0019);

    LcdWriteIndx(0x001F);//R31
    LcdWriteData(0x0028);

    LcdWriteIndx(0x0020);//R32
    LcdWriteData(0x002D);

    // Display On
    LcdWriteIndx(0x003B);//R59
    LcdWriteData(0x0001);

    LcdWriteIndx(0x0000);//R0
    LcdWriteData(0x0000);

    /*LcdWriteIndx(0x0000);
    LcdWriteData(0x0088);// STBY_GOFF=0


    LcdWriteIndx(0x0018);
    LcdWriteData(0x0001);// POWER SUPPL ON SETTING


    LcdWriteIndx(0x0000);
    LcdWriteData(0x0080);// STBY MODE RELEASE*/
}

///////////////////////////////////////////////////////////////////////////////

void Lcm_SetupGPIOs(DisplayContext *pCxt)
{
    // 16bpp support
    // bits 58-77
    GPDR1 |= (0x3f << 26);
    GPDR2 |= 0x00003fff;

    GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
    GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
}

void Lcm_DisplayOn(DisplayContext *pCxt)
{
    SPI2Init();
    LcdHWSetup();
    LcdReset();
    ostdelay(10);
    LcdMitsubishiInit();
}

void Lcm_DisplayOff(DisplayContext *pCxt)
{
}
